package neuralmusic.brain.ga;

import java.awt.Rectangle;
import java.util.Random;
import java.util.TreeSet;

import neuralmusic.brain.IOBrainBuilder;
import neuralmusic.brain.Util;
import neuralmusic.brain.module.Brain;
import neuralmusic.brain.module.NeuronParams;

public class BrainPool implements Pool {

	
	private int nIn;
	private int nOut;

	TreeSet<FitThing> fitThings=new TreeSet<FitThing>();
	
	public BrainPool(int nIn,int nOut) {
	
		this.nIn=nIn;
		this.nOut=nOut;
		
	}
	
	
	public void addToPool(Object o, Fitness fit) {
		fitThings.add(new FitThing(o,fit));
	}
	
	@Override
	public Brain createNewBrain() {
	
		int nInputs = nIn;
		int nOutputs = nOut;
		Random rand = new Random();
		
		int nInternal = 5+rand.nextInt(50);
		int nInternalConnect = 2+rand.nextInt(20);
		int nInToGrey = 1;
		int nGreyToOut = 1;

		
		NeuronParams pramIn = new NeuronParams();
		pramIn.thresh = 1.0f;
		pramIn.delayInSecs = 0.0f; 
		pramIn.outputVal = 1.0f;
		pramIn.timeConstant = (float) Util.halfLifeToTimeConstant(.5);

		
		Float inputConnectWeight = 10.0f;
		
		NeuronParams pramGrey = new NeuronParams();

		pramGrey.delayInSecs = .1f; // will be set by delayMin and Delaymax
		float delayMax=.01f;
		float delayMin=1e-3f;
		pramGrey.outputVal=1.0f;
		pramGrey.timeConstant = (float) (Util
				.halfLifeToTimeConstant(pramGrey.delayInSecs));
		pramGrey.thresh=.5f;
	
		NeuronParams pramOut = new NeuronParams();
		pramOut.thresh = .1f;
		pramOut.delayInSecs = 0; // don't delay outputs		
		pramOut.outputVal = 1.0f;
		pramOut.timeConstant = (float) Util.halfLifeToTimeConstant(.3);

		Float weightInToGrey = 1.0f;
		Float internalConnectWeight = 0.5f;
		Float weightGrayToOut = 1.0f;
		
		Rectangle rect = new Rectangle(0, 0, 400, 200);
	
		
		
		Brain brain = IOBrainBuilder.buildIOBrain(nInputs, nOutputs, nInternal,
				nInternalConnect, nInToGrey, nGreyToOut, pramIn, pramGrey,
				pramOut, inputConnectWeight, weightInToGrey,
				internalConnectWeight, weightGrayToOut, delayMin, delayMax,
				rect, rand);

		
		return brain;
	}


	public FitThing getFitest() {
		if (fitThings.isEmpty()) return null;
		return fitThings.last();
	}

}
